home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / CONFIG.C < prev    next >
C/C++ Source or Header  |  1992-01-20  |  10KB  |  281 lines

  1. /*****************************************************************************
  2. *   General routines to    configuration file reading:                 *
  3. * The config file (same name as program, type .cfg) must have th following   *
  4. * format: one variable setup per line, each line consists of two params.     *
  5. * The first is variable name, which is text string without white spaces.     *
  6. * The second param. contains its value, which might be boolean (TRUE/FALSE), *
  7. * integer, or real type.                             *
  8. *   The main routine should get a structure consists of 3 elements per         *
  9. * variable: the string to match, the variable to save the data read from     *
  10. * config file, and the type (Boolean, Integer, Real), for type checking.     *
  11. * See config.h for exact definition of this data structure.             *
  12. *                                         *
  13. * Version 0.2 - adding String Type.                         *
  14. *                                         *
  15. * Written by:  Gershon Elber                   Ver 0.2, Jan. 1989    *
  16. *****************************************************************************/
  17.  
  18. #ifdef __MSDOS__
  19. #include <stdlib.h>
  20. #include <alloc.h>
  21. #include <conio.h>
  22. #include <dir.h>
  23. #endif /* __MSDOS__ */
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "irit_sm.h"
  28. #include "config.h"
  29.  
  30. /* #define    DEBUG   Uncomment it for simple test case (see config.bat). */
  31.  
  32. #define TAB    9
  33.  
  34. /* Some fatal errors that cause this module to die... */
  35. #define    ERR_ONLY_NAME        1
  36. #define    ERR_BOOL_EXPECTED    2
  37. #define    ERR_INT_EXPECTED    3
  38. #define    ERR_REAL_EXPECTED    4
  39. #define    ERR_STRING_EXPECTED    5
  40. #define    ERR_NOT_EXISTS        6
  41.  
  42. static char *ConfigPath;
  43.  
  44. static void UpdateVariable(char *Line, ConfigStruct *SetUp, int NumVar,
  45.                              int LineCount);
  46. static void PrintConfigError(int ErrorNum, int LineCount);
  47. static FILE *FindFile(char *FileName);
  48.  
  49. /*****************************************************************************
  50. * Routine to print the current configuration data structure contents.         *
  51. *****************************************************************************/
  52. void ConfigPrint(ConfigStruct *SetUp, int NumVar)
  53. {
  54.     int i;
  55.  
  56.     fprintf(stderr, "\nCurrent defaults:\n\n");
  57.  
  58.     for (i = 0; i < NumVar; i++)
  59.         switch (SetUp[i].VarType) {
  60.         case SU_BOOLEAN_TYPE:
  61.         if (* ((int *) SetUp[i].VarData))
  62.             fprintf(stderr, "\t%-20s = TRUE\n", SetUp[i].VarName);
  63.         else
  64.             fprintf(stderr, "\t%-20s = FALSE\n", SetUp[i].VarName);
  65.         break;
  66.         case SU_INTEGER_TYPE:
  67.         fprintf(stderr, "\t%-20s = %d\n", SetUp[i].VarName,
  68.                     * ((int *) SetUp[i].VarData));
  69.         break;
  70.         case SU_REAL_TYPE:
  71. #ifdef __MSDOS__
  72.         fprintf(stderr, "\t%-20s = %g\n", SetUp[i].VarName,
  73. #else
  74.         fprintf(stderr, "\t%-20s = %lg\n", SetUp[i].VarName,
  75. #endif /* __MSDOS__ */
  76.                     * ((RealType *) SetUp[i].VarData));
  77.         break;
  78.         case SU_STRING_TYPE:
  79.         fprintf(stderr, "\t%-20s = \"%s\"\n", SetUp[i].VarName,
  80.                     * ((char **) SetUp[i].VarData));
  81.         break;
  82.     }
  83. }
  84.  
  85. /*****************************************************************************
  86. * Main routine of config module. Gets the program name (it updates the type) *
  87. * PrgmName, and the structure defines the acceptable variables Setup.         *
  88. *****************************************************************************/
  89. void Config(char *PrgmName, ConfigStruct *SetUp, int NumVar)
  90. {
  91.     int i, LineCount = 0;
  92.     char CfgName[PATH_NAME_LEN], Line[LINE_LEN_LONG], *Cptr;
  93.     FILE *f;
  94.  
  95.     i = strlen(PrgmName) - 1;             /* Skip the full path name: */
  96.     while (i && PrgmName[i] != '\\' && PrgmName[i] != '/'
  97.           && PrgmName[i] != ':') i--;
  98.     if (i) i++;
  99.  
  100.     strcpy(CfgName, &PrgmName[i]);
  101.     Cptr = strchr(CfgName, '.');
  102.     if (Cptr != NULL) *Cptr = 0;             /* Delete old type. */
  103.     strcat(CfgName, ".cfg");            /* And add the config file type. */
  104.     if ((f = FindFile(CfgName)) == NULL) return;     /* Search via path var. */
  105.  
  106.     while (!feof(f)) {
  107.     fgets(Line, LINE_LEN_LONG, f);
  108.     LineCount++;
  109.  
  110.     i = 0;    /* Delete all the part after the ; (The comment) if was any. */
  111.     while (Line[i] != 0 && Line[i] != ';') i++;
  112.         if (Line[i]) Line[i] = 0;
  113.  
  114.     i = 0;               /* Now test if that line is empty or not: */
  115.     while (Line[i] != 0 && Line[i] <= ' ') i++;    /* Skip white spaces. */
  116.  
  117.     if (Line[i]) UpdateVariable(Line, SetUp, NumVar, LineCount);
  118.     }
  119.  
  120.     fclose(f);
  121. }
  122.  
  123. /*****************************************************************************
  124. *   Routine to interpret the input Line and update the appropriate variable  *
  125. * in SetUp data structure. NumVar holds number of entries in SetUp Table.    *
  126. *****************************************************************************/
  127. static void UpdateVariable(char *Line, ConfigStruct *SetUp, int NumVar,
  128.                              int LineCount)
  129. {
  130.     int i, j;
  131.     char VarName[LINE_LEN_LONG], VarData[LINE_LEN_LONG], *StrStart, *StrEnd,
  132.     *NewStr;
  133.     RealType Dummy;      /* Force linking of floating point scanf routines. */
  134.  
  135.     i = j = 0;
  136.     while (Line[i] > ' ') {              /* Copy the Variable name: */
  137.     VarName[i] = Line[i];
  138.     i++;
  139.     }
  140.     VarName[i] = 0;
  141.  
  142.     while (Line[i] != 0 && Line[i] <= ' ') i++;
  143.     if (Line[i] == 0) PrintConfigError(ERR_ONLY_NAME, LineCount);
  144.  
  145.     while (Line[i] >= ' ' || Line[i] == TAB)      /* Copy the Variable data: */
  146.     VarData[j++] = Line[i++];
  147.     VarData[j] = 0;
  148.  
  149.     for (i = 0; i < NumVar; i++) if (strcmp(VarName, SetUp[i].VarName) == 0)
  150.     switch (SetUp[i].VarType) {
  151.         case SU_BOOLEAN_TYPE:
  152.         if (strnicmp(VarData, "True", 4) == 0 ||
  153.             strnicmp(VarData, "False", 5) == 0)
  154.             *((int *) SetUp[i].VarData) =
  155.             (strnicmp (VarData, "True", 4) == 0);
  156.         else
  157.             PrintConfigError(ERR_BOOL_EXPECTED, LineCount);
  158.         return;
  159.         case SU_INTEGER_TYPE:
  160.         if (sscanf(VarData, "%d", (int *) SetUp[i].VarData) != 1)
  161.             PrintConfigError(ERR_INT_EXPECTED, LineCount);
  162.         return;
  163.         case SU_REAL_TYPE:
  164. #ifdef __MSDOS__
  165.         if (sscanf(VarData, "%f", &Dummy) != 1) {
  166. #else
  167.         if (sscanf(VarData, "%lf", &Dummy) != 1) {
  168. #endif /* __MSDOS__ */
  169.             PrintConfigError(ERR_REAL_EXPECTED, LineCount);
  170.             return;
  171.         }
  172.         *((RealType *) SetUp[i].VarData) = Dummy;
  173.         return;
  174.         case SU_STRING_TYPE:
  175.         if ((StrStart = strchr(VarData, '"')) != NULL &&
  176.             (StrEnd = strrchr(VarData, '"')) != NULL &&
  177.             StrEnd != StrStart) {
  178.             NewStr = malloc(1 + ((unsigned int) (StrEnd - StrStart)));
  179.             j = 0;
  180.             while (++StrStart != StrEnd) NewStr[j++] = *StrStart;
  181.             NewStr[j] = 0;
  182.             *((char **) SetUp[i].VarData) = NewStr;
  183.         }
  184.         else
  185.             PrintConfigError(ERR_STRING_EXPECTED, LineCount);
  186.         return;
  187.     }
  188.     PrintConfigError(ERR_NOT_EXISTS, LineCount);
  189. }
  190.  
  191. /*****************************************************************************
  192. *   Routine to print fatal configuration file error, and die.             *
  193. *****************************************************************************/
  194. static void PrintConfigError(int ErrorNum, int LineCount)
  195. {
  196.     fprintf(stderr, "Config. file error [%s line %d]: ",
  197.                         ConfigPath, LineCount);
  198.  
  199.     switch (ErrorNum) {
  200.     case ERR_ONLY_NAME:
  201.         fprintf(stderr, "Only Name found.\n");
  202.         break;
  203.         case ERR_BOOL_EXPECTED:
  204.         fprintf(stderr, "Boolean type expected.\n");
  205.         break;
  206.     case ERR_INT_EXPECTED:
  207.         fprintf(stderr, "Integer type expected.\n");
  208.         break;
  209.     case ERR_REAL_EXPECTED:
  210.         fprintf(stderr, "Real type expected.\n");
  211.         break;
  212.     case ERR_STRING_EXPECTED:
  213.         fprintf(stderr, "String (within \") type expected.\n");
  214.         break;
  215.     case ERR_NOT_EXISTS:
  216.         fprintf(stderr, "No such set up option.\n");
  217.         break;
  218.     }
  219.  
  220.     exit('c');
  221. }
  222.  
  223. /*****************************************************************************
  224. *   Routine to search for a file and open it according to attribute at all   *
  225. * directories defined by PATH environment variable and current dir.         *
  226. *****************************************************************************/
  227. static FILE *FindFile(char *FileName)
  228. {
  229.     FILE *f;
  230.  
  231.     ConfigPath = searchpath(FileName);
  232.     if ((f = fopen(ConfigPath, "rt")) != NULL) return f;
  233.  
  234.     fprintf(stderr, "Warning: No config. file (%s) found.\n", FileName);
  235.  
  236.     return NULL;
  237. }
  238.  
  239. #ifdef DEBUG
  240.  
  241. /*****************************************************************************
  242. *   Simple test routine. use it with cnfgtest.bat which rename the program   *
  243. * name so that this module will recognize the appropriate configuration file *
  244. * The arguments below assume double or non MSDOS system!.             *
  245. *****************************************************************************/
  246. void main(int argc, char **argv)
  247. {
  248.     static int Test1, Test2, Test3, Test4;
  249.     static double Test5, Test6;
  250.     static char *Test7, *Test8;
  251.  
  252.     ConfigStruct SetUp[] =
  253.     { { "TestOne",   (VoidPtr) &Test1, SU_BOOLEAN_TYPE },
  254.       { "TestTwo",   (VoidPtr) &Test2, SU_BOOLEAN_TYPE },
  255.       { "Test333",   (VoidPtr) &Test3, SU_INTEGER_TYPE },
  256.       { "Testing4",  (VoidPtr) &Test4, SU_INTEGER_TYPE },
  257.       { "TestReal5", (VoidPtr) &Test5, SU_REAL_TYPE },
  258.       { "TestReal6", (VoidPtr) &Test6, SU_REAL_TYPE },
  259.       { "String7",     (VoidPtr) &Test7, SU_STRING_TYPE },
  260.       { "String8",   (VoidPtr) &Test8, SU_STRING_TYPE } };
  261.  
  262.     Test1 = Test2 = Test3 = Test4 = 9999;
  263.     Test5 = Test6 = 0.9999;
  264.     Test7 = Test8 = NULL;
  265.  
  266.     printf("Before:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
  267.         "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
  268.         Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
  269.  
  270.     Config(*argv, SetUp, 8); /* Do it! */
  271.  
  272.     printf("After:\nTest1 = %d, Test2 = %d, Test3 = %d, Test4 = %d\n"
  273.         "Test5 = %lf, Test6 = %lf\nTest7 = \"%s\"\nTest8 = \"%s\"\n",
  274.         Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8);
  275.  
  276.     printf("\nConfigPrint prints:\n");
  277.     ConfigPrint(SetUp, 8);
  278. }
  279.  
  280. #endif /* DEBUG */
  281.